home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / ppmtouil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-06  |  8.4 KB  |  300 lines

  1. /* ppmtouil.c - read a portable pixmap and produce a Motif UIL icon file
  2. **
  3. ** Converted by Jef Poskanzer from ppmtoxpm.c, which is
  4. ** Copyright (C) 1990 by Mark W. Snitily.
  5. **
  6. ** Permission to use, copy, modify, and distribute this software and its
  7. ** documentation for any purpose and without fee is hereby granted, provided
  8. ** that the above copyright notice appear in all copies and that both that
  9. ** copyright notice and this permission notice appear in supporting
  10. ** documentation.  This software is provided "as is" without express or
  11. ** implied warranty.
  12. */
  13.  
  14. #include <ctype.h>
  15. #include "ppm.h"
  16. #include "ppmcmap.h"
  17.  
  18. /* Max number of colors allowed in ppm input. */
  19. #define MAXCOLORS 256
  20.  
  21. /* Lower bound and upper bound of character-pixels printed in UIL output. */
  22. #define LOW_CHAR '`'
  23. #define HIGH_CHAR '~'
  24.  
  25. typedef struct {    /* character-pixel mapping */
  26.     char* cixel;    /* character string printed for pixel */
  27.     char* rgbname;    /* ascii rgb color, either mnemonic or #rgb value */
  28.     char* barname;    /* ascii rgb color with spaces replaced by underbars */
  29.     } cixel_map;
  30.  
  31. static char* gen_numstr ARGS(( int i, int base, char low_char, int digits ));
  32. static void gen_cmap ARGS(( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP ));
  33.  
  34. void
  35. main( argc, argv )
  36.     int argc;
  37.     char* argv[];
  38.     {
  39.     FILE* ifp;
  40.     pixel** pixels;
  41.     register pixel* pP;
  42.     int argn, rows, cols, ncolors, row, col, i;
  43.     pixval maxval;
  44.     colorhash_table cht;
  45.     colorhist_vector chv;
  46.     cixel_map cmap[MAXCOLORS];
  47.     int charspp;
  48.     char out_name[100];
  49.     char* cp;
  50.     int printed_one;
  51.     char* usage = "[-name <uilname>] [ppmfile]";
  52.  
  53.     ppm_init( &argc, argv );
  54.     out_name[0] = '\0';
  55.  
  56.     argn = 1;
  57.  
  58.     /* Check for command line options. */
  59.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  60.     {
  61.     if ( pm_keymatch( argv[argn], "-name", 2 ) )
  62.         {
  63.         ++argn;
  64.         if ( argn == argc )
  65.         pm_usage( usage );
  66.         (void) strcpy( out_name, argv[argn] );
  67.         }
  68.     else
  69.         pm_usage( usage );
  70.     ++argn;
  71.     }
  72.  
  73.     if ( argn != argc )
  74.     {
  75.     /* Open the input file. */
  76.     ifp = pm_openr( argv[argn] );
  77.  
  78.     /* If output filename not specified, use input filename as default. */
  79.     if ( out_name[0] == '\0' )
  80.         {
  81.         (void) strcpy( out_name, argv[argn] );
  82.         cp = index( out_name, '.' );
  83.         if ( cp != 0 )
  84.         *cp = '\0';    /* remove extension */
  85.         if ( strcmp( out_name, "-" ) == 0 )
  86.         (void) strcpy( out_name, "noname" );
  87.         /* Remove trailing _icon in name. */
  88.         cp = rindex( out_name, '_' );
  89.         if ( cp != (char*) 0 &&
  90.          cp[1] == 'i' && cp[2] == 'c' && cp[3] == 'o' &&
  91.          cp[4] == 'n' && cp[5] == '\0' )
  92.         *cp = '\0';
  93.         }
  94.     ++argn;
  95.     }
  96.     else
  97.     {
  98.     /* No input file specified. */
  99.     ifp = stdin;
  100.     if ( out_name[0] == '\0' )
  101.         (void) strcpy( out_name, "noname" );
  102.     }
  103.  
  104.     if ( argn != argc )
  105.     pm_usage( usage );
  106.  
  107.     /* Read in the ppm file. */
  108.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  109.     pm_close( ifp );
  110.  
  111.     /* Figure out the colormap. */
  112.     pm_message( "computing colormap..." );
  113.     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
  114.     if ( chv == (colorhist_vector) 0 )
  115.     pm_error(
  116.         "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  117.     pm_message( "%d colors found", ncolors );
  118.  
  119.     /* Make a hash table for fast color lookup. */
  120.     cht = ppm_colorhisttocolorhash( chv, ncolors );
  121.  
  122.     /* Now generate the character-pixel colormap table. */
  123.     gen_cmap( chv, ncolors, maxval, cmap, &charspp );
  124.  
  125.     /* Write out the UIL header. */
  126.     fprintf (stdout,  "module %s\n", out_name );
  127.     fprintf (stdout,  "version = 'V1.0'\n" );
  128.     fprintf (stdout,  "names = case_sensitive\n" );
  129.     fprintf (stdout,  "include file 'XmAppl.uil';\n" );
  130.  
  131.     /* Write out the colors. */
  132.     fprintf (stdout,  "\n" );
  133.     fprintf (stdout,  "value\n" );
  134.     for ( i = 0; i < ncolors; ++i )
  135.     if ( cmap[i].barname != (char*) 0 )
  136.         fprintf (stdout, 
  137.         "    %s : color( '%s' );\n", cmap[i].barname, cmap[i].rgbname );
  138.  
  139.     /* Write out the ascii colormap. */
  140.     fprintf (stdout,  "\n" );
  141.     fprintf (stdout,  "value\n" );
  142.     fprintf (stdout,  "  %s_rgb : color_table (\n", out_name );
  143.     printed_one = 0;
  144.     for ( i = 0; i < ncolors; ++i )
  145.     if ( cmap[i].barname != (char*) 0 )
  146.         {
  147.         if ( printed_one )
  148.         fprintf (stdout,  ",\n" );
  149.         fprintf (stdout,  "    %s = '%s'", cmap[i].barname, cmap[i].cixel );
  150.         printed_one = 1;
  151.         }     
  152.     fprintf (stdout,  "\n    );\n" );
  153.  
  154.     /* Write out the ascii character-pixel image. */
  155.     fprintf (stdout,  "\n" );
  156.     fprintf (stdout, 
  157.     "%s_icon : exported icon( color_table = %s_rgb,\n",
  158.     out_name, out_name );
  159.     for ( row = 0; row < rows; ++row )
  160.     {
  161.     fprintf (stdout,  "    '" );
  162.     for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
  163.         {
  164.         if ( ( col * charspp ) % 70 == 0 && col > 0 )
  165.         fprintf (stdout,  "\\\n" );        /* line continuation */
  166.         fprintf (stdout,  "%s", cmap[ppm_lookupcolor(cht, pP)].cixel );
  167.         }
  168.     if ( row != rows - 1 )
  169.         fprintf (stdout,  "',\n" );
  170.     else
  171.         fprintf (stdout,  "'\n") ; 
  172.     }
  173.     fprintf (stdout,  ");\n" );
  174.     fprintf (stdout,  "\n" );
  175.     fprintf (stdout,  "end module;\n" );
  176.  
  177.     pm_close (stdout);
  178.  
  179.     exit( 0 );
  180.     }
  181.  
  182. /* Given a number and a base, this routine prints the number into a
  183. ** malloc'ed string and returns it.  The length of the string is
  184. ** specified by "digits".  The ascii characters of the printed
  185. ** number range from low_char to low_char + base.  The string is
  186. ** low_char filled.
  187. */
  188.  
  189. #if __STDC__
  190. static char*
  191. gen_numstr( int i, int base, char low_char, int digits )
  192. #else /*__STDC__*/
  193. static char*
  194. gen_numstr( i, base, low_char, digits )
  195.     int i, base, digits;
  196.     char low_char;
  197. #endif /*__STDC__*/
  198.     {
  199.     char* str;
  200.     char* p;
  201.     int d;
  202.  
  203.     /* Allocate memory for printed number.  Abort if error. */
  204.     str = (char*) malloc( digits + 1 );
  205.     if ( str == 0 )
  206.     pm_error( "out of memory allocating number string" );
  207.  
  208.     /* Generate characters starting with least significant digit. */
  209.     p = str + digits;
  210.     *p-- = '\0';    /* nul terminate string */
  211.     while ( p >= str )
  212.     {
  213.     d = i % base;
  214.     i /= base;
  215.     *p-- = low_char + d;
  216.     }
  217.  
  218.     return str;
  219.     }
  220.  
  221. #if __STDC__
  222. static void
  223. gen_cmap( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP )
  224. #else /*__STDC__*/
  225. static void
  226. gen_cmap( chv, ncolors, maxval, cmap, charsppP )
  227.     colorhist_vector chv;
  228.     int ncolors;
  229.     pixval maxval;
  230.     cixel_map cmap[MAXCOLORS];
  231.     int* charsppP;
  232. #endif /*__STDC__*/
  233.     {
  234.     int i, j, base;
  235.     char* colorname;
  236.     char* cp1;
  237.     char* cp2;
  238.  
  239.     /* Figure out how many characters per pixel we'll be using.  Don't want
  240.     ** to be forced to link with libm.a, so using a division loop rather than
  241.     ** a log function.
  242.     */
  243.     base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
  244.     for ( *charsppP = 0, i = ncolors; i > 0; ++(*charsppP) )
  245.     i /= base;
  246.  
  247.     /* Generate the character-pixel string and the rgb name for each colormap
  248.     ** entry.
  249.     */
  250.     for ( i = 0; i < ncolors; ++i )
  251.     {
  252.     /* Generate color name string. */
  253.     colorname = ppm_colorname( &(chv[i].color), maxval, 0 );
  254.  
  255.     /* Check whether we've already assigned a character to this name,
  256.     ** via the closest-match code.
  257.     */
  258.     for ( j = 0; j < i; ++j )
  259.         {
  260.         if ( cmap[j].rgbname != (char*) 0 &&
  261.          strcmp( colorname, cmap[j].rgbname ) == 0 )
  262.         {
  263.         cmap[i].cixel = cmap[j].cixel;
  264.         cmap[i].rgbname = (char*) 0;
  265.         cmap[i].barname = (char*) 0;
  266.         goto nexti;
  267.         }
  268.         }
  269.  
  270.     /* Copy it. */
  271.     cmap[i].rgbname = (char*) malloc( strlen( colorname ) + 1 );
  272.     if ( cmap[i].rgbname == 0 )
  273.         pm_error( "out of memory allocating color name" );
  274.     (void) strcpy( cmap[i].rgbname, colorname );
  275.  
  276.     /* Copy it again and replace the blanks with underbars. */
  277.     cmap[i].barname = malloc( strlen( colorname ) + 1 );
  278.     if ( cmap[i].barname == 0 )
  279.         pm_error( "out of memory allocating color name", 0,0,0,0,0 );
  280.     cp1 = colorname;
  281.     cp2 = cmap[i].barname;
  282.     for ( ; ; )
  283.         {
  284.         if ( *cp1 == ' ' )
  285.         *cp2 = '_';
  286.         else
  287.         *cp2 = *cp1;
  288.         if ( *cp1 == '\0' )
  289.         break;
  290.         ++cp1;
  291.         ++cp2;
  292.         }
  293.  
  294.     /* Generate color value characters. */
  295.     cmap[i].cixel = gen_numstr( i, base, LOW_CHAR, *charsppP );
  296.  
  297.     nexti: ;
  298.     }
  299.     }
  300.